package com.bolt.support.spring.jpa.jpql;

import com.bolt.common.reflect.ClassUtil;
import com.bolt.common.reflect.ReflectionUtil;
import com.bolt.common.utils.StrUtil;

import java.lang.reflect.Field;

public abstract class BaseClause<T, Children extends BaseClause, V> extends SqlFuncClause<T, Children> {

    protected final Children typedThis = (Children) this;

    protected String alias;

    protected String owned;

    protected String property;

    protected Class<V> type;


    public BaseClause(String property, String owned, String alias, Class<V> type) {
        this.property = property;
        this.alias = alias;
        this.owned = owned;
        this.type = type;
    }

    public Children as(String alias) {
        this.alias = alias;
        return typedThis;
    }

    public String getParamName() {
        return StrUtil.isBlank(this.alias) ? this.property : this.alias;
    }

    protected String createOwnedName(Class<V> type) {
        String className = ClassUtil.getClassName(type, true);
        return StrUtil.lowerFirst(className);
    }

    public Children getTypedThis() {
        return typedThis;
    }

    public String getAlias() {
        return alias;
    }

    public void setAlias(String alias) {
        this.alias = alias;
    }

    public String getOwned() {
        return owned;
    }

    public void setOwned(String owned) {
        this.owned = owned;
    }

    public String getProperty() {
        return property;
    }

    public void setProperty(String property) {
        this.property = property;
    }

    public Class<V> getType() {
        return type;
    }

    public void setType(Class<V> type) {
        this.type = type;
    }


    public Field getPropertyField() {
       return ReflectionUtil.getAccessibleField(this.type, this.property);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        BaseClause<?, ?, ?> that = (BaseClause<?, ?, ?>) o;

        if (owned != null ? !owned.equals(that.owned) : that.owned != null) return false;
        if (!property.equals(that.property)) return false;
        return type != null ? type.equals(that.type) : that.type == null;
    }

    @Override
    public int hashCode() {
        int result = owned != null ? owned.hashCode() : 0;
        result = 31 * result + property.hashCode();
        result = 31 * result + (type != null ? type.hashCode() : 0);
        return result;
    }
}

 